package com.engine.salary.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.salary.entity.salaryformula.ExpressFormula;
import com.engine.salary.entity.salaryformula.config.FormluaConfig;
import com.engine.salary.entity.salaryformula.po.FormulaPO;
import com.engine.salary.entity.salaryformula.po.FormulaVar;
import com.engine.salary.entity.salaryitem.po.SalaryItemPO;
import com.engine.salary.entity.salarysob.bo.SalarySobBackItemBO;
import com.engine.salary.entity.salarysob.dto.SalarySobBackItemDTO;
import com.engine.salary.entity.salarysob.param.SalarySobBackItemSaveParam;
import com.engine.salary.entity.salarysob.po.SalarySobBackItemPO;
import com.engine.salary.entity.salarysob.po.SalarySobPO;
import com.engine.salary.enums.SalaryValueTypeEnum;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.mapper.salarysob.SalarySobBackItemMapper;
import com.engine.salary.service.SalaryFormulaService;
import com.engine.salary.service.SalaryItemService;
import com.engine.salary.service.SalarySobBackItemService;
import com.engine.salary.service.SalarySobService;
import com.engine.salary.util.SalaryDateUtil;
import com.engine.salary.util.SalaryEntityUtil;
import com.engine.salary.util.SalaryI18nUtil;
import com.engine.salary.util.db.MapperProxyFactory;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.math.NumberUtils;
import weaver.hrm.User;

import java.time.LocalDateTime;
import java.util.*;

/**
 * @author Harryxzy
 * @date 2022/11/15 16:19
 * @description 薪资账套的回算项目
 */
public class SalarySobBackItemServiceImpl extends Service implements SalarySobBackItemService {

    private SalarySobBackItemMapper getSalarySobBackItemMapper() {
        return MapperProxyFactory.getProxy(SalarySobBackItemMapper.class);
    }

    private SalarySobService getSalarySobService(User user) {
        return ServiceUtil.getService(SalarySobServiceImpl.class, user);
    }

    private SalaryItemService getSalaryItemService(User user) {
        return ServiceUtil.getService(SalaryItemServiceImpl.class, user);
    }

    private SalaryFormulaService getSalaryFormulaService(User user) {
        return ServiceUtil.getService(SalaryFormulaServiceImpl.class, user);
    }

    @Override
    public List<SalarySobBackItemPO> listBySalarySobId(Long salarySobId) {
        return getSalarySobBackItemMapper().listSome(SalarySobBackItemPO.builder().salarySobId(salarySobId).build());
    }

    @Override
    public List<SalarySobBackItemPO> listAll() {
        return getSalarySobBackItemMapper().listAll();
    }

    @Override
    public void batchInsert(List<SalarySobBackItemPO> needInsertSalarySobBackItems) {
        List<List<SalarySobBackItemPO>> partition = Lists.partition(needInsertSalarySobBackItems, 100);
        partition.forEach(getSalarySobBackItemMapper()::batchInsert);
    }

    @Override
    public SalarySobBackItemPO getById(Long salarySobBackItemId) {
        return getSalarySobBackItemMapper().getById(salarySobBackItemId);
    }

    @Override
    public List<SalarySobBackItemDTO> save(SalarySobBackItemSaveParam saveParam) {
        // 查询薪资账套是否存在
        SalarySobPO salarySobPO = getSalarySobService(user).getById(saveParam.getSalarySobId());
        if (Objects.isNull(salarySobPO)) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98769, "薪资账套不存在或已被删除"));
        }
        // 查询薪资账套下的回算薪资项目
        SalarySobBackItemPO salarySobBackItem = getById(saveParam.getId());
        if (Objects.isNull(salarySobBackItem)) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "回算薪资项目不存在或已被删除"));
        }
        // 查询薪资项目
        SalaryItemPO salaryItem = getSalaryItemService(user).getById(saveParam.getSalaryItemId());
        if (salaryItem == null) {
            throw new SalaryRunTimeException("参数错误，项目不存在或已被删除");
        }
        salarySobBackItem.setRoundingMode(saveParam.getRoundingMode().getValue());
        salarySobBackItem.setPattern(saveParam.getPattern());
        salarySobBackItem.setValueType(saveParam.getValueType().getValue());
        salarySobBackItem.setFormulaId(saveParam.getValueType() == SalaryValueTypeEnum.INPUT ? NumberUtils.LONG_ZERO : saveParam.getFormulaId());
        salarySobBackItem.setUpdateTime(SalaryDateUtil.localDateTimeToDate(LocalDateTime.now()));
        getSalarySobBackItemMapper().updateIgnoreNull(salarySobBackItem);

        // 查询公式
        List<ExpressFormula> expressFormulas = getSalaryFormulaService(user).listExpressFormula(Collections.singleton(salarySobBackItem.getFormulaId()));
        return SalarySobBackItemBO.convert2DTO(Collections.singletonList(salarySobBackItem), Collections.singletonList(salaryItem), expressFormulas);
    }

    @Override
    public Long getCountBySalarySobIdIn(Collection<Long> salarySobIds) {
        return getSalarySobBackItemMapper().countBySalarySobIdIn(salarySobIds);
    }

    @Override
    public int deleteBySalarySobIds(Collection<Long> salarySobIds) {
        return getSalarySobBackItemMapper().deleteBySalarySobIds(salarySobIds);
    }

    @Override
    public List<SalarySobBackItemPO> listBySalaryItemIds(Collection<Long> salaryItemIds) {
        return getSalarySobBackItemMapper().listSome(SalarySobBackItemPO.builder().salaryItemIds(salaryItemIds).build());
    }

    @Override
    public List<SalarySobBackItemPO> getConfig(Long salarySobId) {
        List<SalarySobBackItemPO> salarySobBackItemPOS = listBySalarySobId(salarySobId);
        if (CollectionUtil.isNotEmpty(salarySobBackItemPOS)) {
            FormluaConfig config = getSalaryFormulaService(user).getConfig();
            List<FormulaPO> formulaPOS = config.getFormulas();
            Map<Long, FormulaPO> formulaMap = SalaryEntityUtil.convert2Map(formulaPOS, FormulaPO::getId);
            List<FormulaVar> formulaVars = config.getFormulaVars();
            Map<Long, List<FormulaVar>> varListMap = SalaryEntityUtil.group2Map(formulaVars, FormulaVar::getFormulaId);

            List<SalaryItemPO> salaryItems = getSalaryItemService(user).listAll();
            Map<Long, SalaryItemPO> itemIdMap = SalaryEntityUtil.convert2Map(salaryItems, SalaryItemPO::getId);

            salarySobBackItemPOS.forEach(po -> {
                if (SalaryEntityUtil.isNotNullOrEmpty(po.getFormulaId())) {
                    FormulaPO formulaPO = formulaMap.get(po.getFormulaId());
                    if (SalaryEntityUtil.isNotNullOrEmpty(formulaPO)) {
                        List<FormulaVar> formulaVarList = varListMap.getOrDefault(formulaPO.getId(), new ArrayList<>());
                        formulaPO.setFormulaVars(formulaVarList);
                    }
                    po.setFormula(formulaPO);
                }
                if(SalaryEntityUtil.isNotNullOrEmpty(po.getSalaryItemId())){
                    SalaryItemPO salaryItemPO = itemIdMap.get(po.getSalaryItemId());
                    po.setSalaryItem(salaryItemPO);
                }

            });
        }
        return salarySobBackItemPOS;
    }

}
